import { useRef, useState, useEffect } from "react";
import { Button, message, Progress, Spin } from "antd";
import '../../css/csy/fileUploader.css';
import { InboxOutlined } from "@ant-design/icons";
import useDrag from './Hooks/useDrag';
import { CHUNK_SIZE, MAX_RETRIES } from './constant';
import { postmerge1, postUpload, postVerify } from '../../api/csy/api'
import axios from "axios";
import Context from './input'
import { NavBar, Toast } from 'antd-mobile'
import { useNavigate } from "react-router-dom";

type FilePreview = {
    url: string;
    type: string;
} | null;

// 定义上传的状态
const UploadStatus = {
    NOT_STARTED: "NOT_STARTED", // 初始状态,尚未开始上传
    UPLOADING: "UPLOADING",// 上传中(包括暂停后恢复上传)
    PAUSED: "PAUSED", // 暂停
}
type Cancel = {
    cancel: (message: string) => void;
};


function FileUploader() {
    const uploadContainerRef = useRef<HTMLDivElement>(null);
    const { selectedFile, filePreView, resetFileStatus } = useDrag(uploadContainerRef);
    const [uploadProgress, setUploadProgress] = useState<Record<string, number>>({});
    const [path, setPath] = useState<string>('')

    // 计算平均值
    const renderTotalProgress = () => {
        const percents = Object.values(uploadProgress)
        const totalPercent = Math.round(
            percents.reduce((pre, cur) => pre + cur, 0) / percents.length);
        return (
            <div>
                <span>总进度:</span>
                <Progress percent={totalPercent} />
            </div>
        )

    }
    //控制上传的状态
    const [uploadStatus, setUploadStatus] = useState(UploadStatus.NOT_STARTED)
    //存放所有上传请求的取消的token
    const [cancelTokens, setCancelTokens] = useState<Cancel[]>([]);


    const restAllStatus = () => {
        // resetFileStatus()
        setUploadProgress({})
        //重置状态方法中添加修改上传状态为初始状态
        setUploadStatus(UploadStatus.NOT_STARTED)
    }

    //定义worker
    const [filenameWorker, setFilenameWorker] = useState<Worker | null>(null);
    //定义一个是否在计算文件hash名的状态
    const [isCalculatingFileName, setIsCalculatingFileName] = useState(false);

    useEffect(() => {
        //创建worker实例
        const filenameWorker = new Worker('/filenamWorker.js')
        setFilenameWorker(filenameWorker)
        // 在 worker 中监听计算结果
        filenameWorker.onmessage = (event) => {
            // 在这里处理 worker 发送回来的结果
            console.log('Worker result:', event.data);
            setIsCalculatingFileName(false); // 计算结束后更新状态
        };

        // 清理工作，终止 worker
        return () => {
            filenameWorker.terminate();
        };
    }, [])






    // 获取文件名
    const handleUpload = async () => {
        if (!selectedFile) {
            message.error("你尚未选中任何文件！");
            return;
        }
        //上传状态该为上传中
        setUploadStatus(UploadStatus.UPLOADING)
        //向worker发送消息计算好的文件名
        filenameWorker?.postMessage(selectedFile)
        setIsCalculatingFileName(true); // 开始计算时更新状态
        (filenameWorker as Worker).onmessage = async (event) => {
            if (event.data) {
                setPath(event.data); // 更新文件路径
            } else {
                console.error("文件名计算失败，返回值为 undefined");
            }
            setIsCalculatingFileName(false);

            await uploadFile(
                selectedFile,
                event.data, // 事件数据即文件名
                setUploadProgress,
                restAllStatus,
                setCancelTokens
            )
        };
        //传参加上setcancelTOkens方法
        // const fileName = await getFileName(selectedFile);
    };


    //暂停上传
    const pauseUpload = async () => {
        setUploadStatus(UploadStatus.PAUSED)
        cancelTokens.forEach(cancelTokens => cancelTokens.cancel('暂停上传'))
    }

    //根据上传状态的不同,页面也就显示不同的按钮
    const renderButton = () => {
        switch (uploadStatus) {
            case UploadStatus.NOT_STARTED:
                return <Button type="primary" style={{ marginTop: '1rem' }} onClick={handleUpload}>开始上传</Button>
            case UploadStatus.UPLOADING:
                return <Button type="primary" style={{ marginTop: '1rem' }} danger onClick={pauseUpload}>暂停上传</Button>
            case UploadStatus.PAUSED:
                return <Button type="primary" style={{ marginTop: '1rem' }} onClick={handleUpload}>恢复上传</Button>
        }
    }



    const renderProgress = () => {
        //上传状态为非初始状态页面才显示切片进度和总进度
        if (uploadStatus !== UploadStatus.NOT_STARTED) {
            let totalProgress = renderTotalProgress();
            let chunkProgress = Object.keys(uploadProgress).map(
                (chunkName, index) => (
                    <div key={chunkName}>
                        <span>切片{index}</span>
                        <Progress percent={uploadProgress[chunkName]}></Progress>
                    </div>
                )
            )
            return (
                <>
                    {totalProgress}
                    {chunkProgress}
                </>
            )
        }
    }

    const navigate = useNavigate()
    const back = () => {
        navigate(-1)
        sessionStorage.setItem('integralShop', JSON.stringify({flag: true}))
    }
    const img = localStorage.getItem('savedImage');

    const previewData = filePreView || (img ? { url: img, type: 'image/png' } : null);

    function renderFilePreview(filePreview: FilePreview) {

        if (!filePreview) {
            return <InboxOutlined />;
        }

        const { url, type } = filePreview;


        if (url) {
            if (type.startsWith('video/')) {
                return <video src={url} controls />;
            } else if (type.startsWith('image/')) {
                return <img src={url} alt="preview" />;
            } else {
                return url;
            }
        } else {
            return <InboxOutlined />;
        }
    }


    return (
        <>
            <NavBar onBack={back}></NavBar>
            <div className="bigbox">
                <div className="upload-container" ref={uploadContainerRef}>
                    {renderFilePreview(previewData)} {/* 确保 img 为 null 时才传 null */}
                </div>
                {renderButton()}
                {/* 计算文件名时给个加载状态的样式 */}
                {isCalculatingFileName && (
                    <Spin>
                        <span>正在计算文件名</span>
                    </Spin>
                )}
                {renderProgress()}
                <Context path={path}></Context>
            </div>

        </>
    );
}


//实现切片上传大文件
async function uploadFile(file: File,
    fileName: string,
    setUploadProgress: any,
    resetAllStatus: any,
    setCancelTokens: any,
    retryCount = 0 //重试次数
) {
    try {
        const { data } = await postVerify({ fileName });
        if (data.code === 200) {
            message.success("文件已存在,秒传成功");
            return resetAllStatus();
        }
        const chunks = createFileChunks(file, fileName);
        const newCancelTokens = [] as any[];
        const requests = chunks.map(({ chunk, chunkFileName }) => {
            const cancelToken = axios.CancelToken.source();
            newCancelTokens.push(cancelToken);

            const uploadedChunks = data.uploadedChunkList || [];
            const existingChunk = uploadedChunks.find((uploadChunk: any) => uploadChunk.chunkFileName === chunkFileName);

            // 如果块已经上传过了，则跳过上传
            if (existingChunk) {
                const uploadSize = existingChunk.size;
                const remainingChunk = chunk.slice(uploadSize);

                if (remainingChunk.size === 0) {
                    //全部上传完毕，修改进度条百分比为100%
                    // setUploadProgress((prevProgress: any) => ({
                    //     ...prevProgress,
                    //     [chunkFileName]: 100
                    // }))
                    return Promise.resolve(); // 跳过已上传的块
                }
                //未完全上传，给个默认进度值，即计算下之前的值
                // setUploadProgress((prevProgress: any) => ({
                //     ...prevProgress,
                //     [chunkFileName]: (uploadSize / chunk.size)
                // }))

                return createRequest({ fileName, chunk: remainingChunk, chunkFileName },
                    setUploadProgress, cancelToken, uploadSize, chunk.size);
            }

            return createRequest({ fileName, chunk, chunkFileName },
                setUploadProgress, cancelToken, 0, chunk.size);
        });

        setCancelTokens(newCancelTokens);

        // 等待所有块上传完成
        await Promise.all(requests);


        // 所有块上传完成后，调用合并接口
        await postmerge1({ fileName })

        message.success("文件上传成功！");
        resetAllStatus(); // 上传成功后重置状态

    } catch (error) {
        if (axios.isCancel(error)) {
            console.log("上传暂停");
            message.warning("上传暂停");
        } else {

            if (retryCount < MAX_RETRIES) {
                console.log("上传出错了，重试中...");
                uploadFile(file, fileName, setUploadProgress, resetAllStatus, setCancelTokens, retryCount + 1);
            } else {
                console.log("上传出错", error);
                message.error("上传出错");
            }

        }
    }
}


type UploadData = {
    fileName: string;
    chunk: Blob;
    chunkFileName: string;
};

function createRequest(
    { fileName, chunk, chunkFileName }: UploadData,
    setUploadProgress: (progress: Record<string, number>) => void,
    cancelToken: any,
    start: any, // 添加接收参数start
    totaSize: any // 添加接收参数titalSize
) {
    return postUpload({ fileName, chunk, chunkFileName, cancelToken, start, totaSize }, setUploadProgress);
}






function createFileChunks(file: File, fileName: string) {
    //切成的分片数组
    let chunks = []
    let count = Math.ceil(file.size / CHUNK_SIZE);
    for (let i = 0; i < count; i++) {
        let chunk = file.slice(i * CHUNK_SIZE, (i + 1) * CHUNK_SIZE)
        chunks.push({
            chunk,
            chunkFileName: `${fileName}-${i}`
        })
    }
    return chunks
}


//根据文件对象获取文件内容得到的hash文件名
// async function getFileName(file: File) {
//     const fileHash = await calculateFileHash(file); // 计算文件的hash值
//     const fileExtension = file.name.split('.').pop(); // 获取文件扩展名
//     return `${fileHash}.${fileExtension}`; // 返回hash文件名
// }

// async function calculateFileHash(file: File) {
//     const arrayBuffer = await file.arrayBuffer(); //    将文件转换为ArrayBuffer
//     const hashBuffer = await crypto.subtle.digest('SHA-256', arrayBuffer)
//     return bufferToex(hashBuffer); // 将hashBuffer转换为十六进制字符串
// }

// //将ArrayBuffer转换为十六进制字符串
// function bufferToex(buffer: ArrayBuffer) {
//     return Array.from(new Uint8Array(buffer)).map(b => b.toString(16).padStart(2, '0')).join('');
// }




// 显示文件预览信息





export default FileUploader;

